package cn.remex.db.rsql;

import cn.remex.core.cache.DataCachePool;
import cn.remex.core.exception.ServiceCode;
import cn.remex.core.reflect.ReflectUtil;
import cn.remex.core.util.Assert;
import cn.remex.core.util.Judgment;
import cn.remex.core.util.Param;
import cn.remex.core.util.ReadOnlyMap;
import cn.remex.core.util.StringHelper;
import cn.remex.db.Database;
import cn.remex.db.DbCvo;
import cn.remex.db.DbRvo;
import cn.remex.db.exception.RsqlConnectionException;
import cn.remex.db.rsql.connection.RDBManager;
import cn.remex.db.rsql.connection.dialect.Dialect;
import cn.remex.db.rsql.model.Modelable;
import cn.remex.db.sql.ColumnType;
import cn.remex.db.sql.FieldType;
import cn.remex.db.sql.NamedParam;
import cn.remex.db.sql.Select;
import cn.remex.db.sql.SqlColumn;
import cn.remex.db.sql.SqlType;
import org.apache.oro.text.regex.MatchResult;

import javax.persistence.Column;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.sql.Types;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import java.util.function.BiConsumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public final class RsqlUtils implements RsqlConstants {
	//=======================帮助判断的一些工具函数=========================================================//
	public static boolean modelIdIsNew(Object objId) {
		return Judgment.nullOrBlank(objId) || "-1".equals(objId)|| "_empty".equals(objId); // ""，null，-1代表新生状态的id
	}

	//=======================分析处理带命名参数的SQL语句。使用Map存储参数，然后将参数替换成?=====================//
	private static final String NamedSqlEquationRegex = "(([_\\.\\w\u4e00-\u9fa5]+)=:)";
	private static final String NamedSqlEquationRegexRplc = ":";// 这个必须最后替换
	private static final String NamedSqlParamRegex = "(:([_\\.\\w\u4e00-\u9fa5]+))";
	private static final String NamedSqlParamRegexRplc = "(:([_\\.\\w\u4e00-\u9fa5]+))";
	/*把带有:[参数名字]的sql字符串格式化成 一种是【:名字】 一种是【名字=:】 注意不要出现变量名交叉，如word=:word。不管是哪一种，都会自动将包含下划线"_"的分割字符串变成首字母小写,分割单词首字母大写的变量指代字母 如:prsn_name变成prsnName*/
	public static TreeMap<Integer,String> obtainNamedParamIndexs(final String sql) {
		TreeMap<Integer,String> paramsMap = new TreeMap<Integer,String>();

		Pattern p1 = Pattern.compile(NamedSqlParamRegex);
		Pattern p2 = Pattern.compile(NamedSqlEquationRegex);
		Matcher m1 = p1.matcher(sql);
		Matcher m2 = p2.matcher(sql);
		int idx = 1, stt1 = 10000, stt2 = 10000;// 变量大小不能超过10000个字符
		boolean b1 = m1.find();
		boolean b2 = m2.find();
		while (true) {
			if (!b1 && !b2)
			{
				break;// 如果:(word)和(word)=:两种形式的参数都没有则中断
			}
			if (b1)
			{
				stt1 = m1.start();// 查找下一个:(word)出现的位置
			}
			if (b2)
			{
				stt2 = m2.start();// 查找下一个(word)=:出现的位置
			}
			// 在检索到变量的同时，必须优先处理先出现的变量
			if (b1 && !b2 // 当有:(word)没有(word)=:
					|| b1 && stt1 < stt2) { // 当同时有时，:(word)在前面
				String word = m1.group(2);
				paramsMap.put(new Integer(idx++),word);
				b1 = m1.find();
				if (b1) {
					stt1 = m1.start();
				}
			} else if (b2 && !b1 // 当有(word)=:没有:(word)
					|| b2 && stt2 < stt1) { // 当同时有时，(word)=:在前面
				String word = m2.group(2);
				paramsMap.put(new Integer(idx++),word);// 还要进一步处理
				b2 = m2.find();
				if (b2) {
					stt2 = m2.start();
				}
			}
		}
		return paramsMap;
	}
	/*
	 * 把sqlString命名参数化。sqlString支持两种参数,在此以名为name的参数说明。 <p>[name= :name]此种命名将会被解析器解析为[name =?]注意等号与冒号之间的空格。<br> <p>[name=:]<br>此种命名将会被解析为[name=?]<br>
	 * <b>注意第一种方法必须在等号(=)与(:)之间的空格，如果没有空格[name=:name]将被转化为[name=?name]<br>
	 * 这样式错误的</b><br>
	 * 以上两种命名方法都可以在转化为含问号的参数的同时生成一个对应的{@link NamedParam}<br>
	 * 生成是调用了{@link NamedParam#setName(String)}把上面的参数[name]填写进去。
	 */
	public static String obtainNamedSql(String sqlString) {
		sqlString = sqlString.replaceAll(NamedSqlParamRegexRplc, "?");// 这个必须先把
		// :namedParam换成
		// ?
		return sqlString.replaceAll(NamedSqlEquationRegexRplc, "?");// 这个必须后剩下的都是=:
		// 就把:换成?

	}

	//================================一系列SQL列定义，约束的方法============================================//
	private static Map<Type, ColumnType> SqlTypes;
	private static Map<String, ColumnType> SysCreateColumns;
	private static Map<String, ColumnType> SysModifyColumns;
	public static Map<String, ColumnType> SysColumns;
	static {
		SysCreateColumns = new ReadOnlyMap<>();
		SysCreateColumns.put(SYS_createOperator, new ColumnType(Types.CHAR, 16));
		SysCreateColumns.put(SYS_createTime, new ColumnType(Types.TIMESTAMP, 0));
		SysCreateColumns.put(SYS_ownership, new ColumnType(Types.CHAR, 16));

		SysModifyColumns = new ReadOnlyMap<>();
		SysModifyColumns.put(SYS_modifyOperator, new ColumnType(Types.CHAR, 16));
		SysModifyColumns.put(SYS_modifyTime, new ColumnType(Types.TIMESTAMP, 0));

		SysColumns = new ReadOnlyMap<>();
		SysColumns.put(SYS_id, new ColumnType(Types.CHAR, 50, 0, false));
		SysColumns.putAll(SysCreateColumns);
		SysColumns.putAll(SysModifyColumns);

		SqlTypes = new ReadOnlyMap<>();
		SqlTypes.put(short.class,       new ColumnType(Types.INTEGER, 22, 0));
		SqlTypes.put(Short.class,       new ColumnType(Types.INTEGER, 22, 0));
		SqlTypes.put(int.class,         new ColumnType(Types.INTEGER, 22, 0));
		SqlTypes.put(Integer.class,     new ColumnType(Types.INTEGER, 22, 0));
		SqlTypes.put(long.class,        new ColumnType(Types.NUMERIC, 22, 0));
		SqlTypes.put(Long.class,        new ColumnType(Types.NUMERIC, 22, 0));
		SqlTypes.put(double.class,      new ColumnType(Types.DOUBLE, 22, 2));
		SqlTypes.put(Double.class,      new ColumnType(Types.DOUBLE, 22, 2));
		SqlTypes.put(float.class,       new ColumnType(Types.FLOAT, 22, 2));
		SqlTypes.put(Float.class,       new ColumnType(Types.FLOAT, 22, 2));
		SqlTypes.put(boolean.class,     new ColumnType(Types.BOOLEAN, 5));
		SqlTypes.put(Boolean.class,     new ColumnType(Types.BOOLEAN, 5));
		SqlTypes.put(byte.class,        new ColumnType(Types.BIT, 0));
		SqlTypes.put(Byte.class,        new ColumnType(Types.BIT, 0));
		SqlTypes.put(char.class,        new ColumnType(Types.CHAR, 0));
		SqlTypes.put(Character.class,   new ColumnType(Types.CHAR, 0));

		SqlTypes.put(String.class, new ColumnType(Types.CHAR, 100));
		SqlTypes.put(Enum.class, new ColumnType(Types.CHAR, 100));//定义所有枚举的默认SQL类型

		SqlTypes.put(Date.class, new ColumnType(Types.TIMESTAMP, 0));
		SqlTypes.put(LocalDateTime.class, new ColumnType(Types.TIMESTAMP, 0));
		SqlTypes.put(LocalDate.class, new ColumnType(Types.DATE, 0));
		SqlTypes.put(LocalTime.class, new ColumnType(Types.TIME, 0));
	}
	/* 用于获取JavaBean的系统列*/
	static Map<String, ColumnType> obtainColumnTypeOfSysColumn() {
		return SysColumns;
	}
	/* 用于获取JavaBean应该对应的列*/
	static Map<String, ColumnType> obtainColumnType(Class<?> beanClass, SqlColumn rootColumn, FieldType tType) {
		// 添加bean中的基本数据属性，定义为数据库中的字段
		HashMap<String, ColumnType> columns = new HashMap<>();
		SqlType.getFields(beanClass, tType).forEach((fieldName, fieldType)-> {
			if(null==rootColumn ||  !rootColumn.hasAnyColumn() || rootColumn.anyMatchInRoot(fieldName)) {
				//此用于移除没有限定的字段，现在是通过with*或assign*系列功能函数实现的。
				columns.put(fieldName, tType == FieldType.TObject ? new ColumnType(Types.CHAR, 50) : obtainSQLType(fieldType, fieldName, beanClass));
			}
		});
		SysColumns.keySet().forEach(columns::remove);//移除系统列
		return columns;
	}
	/*此函数用于提取基本表中的数据类型。*/
	private static ColumnType obtainSQLType(final Type type, final String fieldName, final Class<?> beanClass) {
		Column at = null != beanClass && null != fieldName?ReflectUtil.getAnnotation(beanClass, fieldName, Column.class):null;
		ColumnType sqlType =null;
		// 如果属性的类型是预定义的类型（SqlTypes中包含的都是预定好受支持的类型），且列的Sql类型通过Column声明定义了
		if (null != beanClass  && null !=(sqlType=SqlTypes.get(type)) && null!=at ) {
			return new ColumnType(SqlTypes.get(type),at);
		}

		// null则表明不是TBase
		// 是ormBeans对象，对象都保存id索引(Enum例外)，所以都是Types.INTEGER
		if (null != sqlType) {
			return sqlType;
		}else{
			if (SqlType.isTObject(type)) {
				return new ColumnType(Types.CHAR, 50);
				// 对象型有普通对象和enum，enum保存为Char
			} else if (Enum.class.isAssignableFrom(ReflectUtil.obtainClass(type))) {
				return null == at ? new ColumnType(Types.CHAR, 100) : new ColumnType(SqlTypes.get(Enum.class), at);
			} else {// 已经定义的Java类型与SqlType类型对应的，从SqlTypes获取，没有的话
				ColumnType retColumnType = SqlTypes.get(type);
				Assert.notNullAndEmpty(retColumnType, ServiceCode.FAIL, "未对Java类型" + type + "配置明确的SqlTypes类型");
				return retColumnType;
			}
		}
	}
	/*此函数用于从Java类型判断出对应的Sql数据类型*/
	public static ColumnType obtainSQLType(Class clazz) {
		return obtainSQLType(clazz, null, null);
	}

	//================================3个表关系便捷操作的SQL方法================================================//
	/*根据neamClass和field查询一对多或多对多映射的子集合collection**/
	public static DbRvo doListColumn_select(String spaceName, final Class<?> beanClass, final String fieldName, final Object beanId) {
		Dialect dialect = RDBManager.getLocalSpaceConfig(spaceName).getDialect();
		String beanName = StringHelper.getClassSimpleName(beanClass);
		Type fieldType = SqlType.getFields(beanClass, FieldType.TCollection).get(fieldName);
		StringBuilder sqlString = new StringBuilder();
		Class<?> subBeanClass = ReflectUtil.getListActualType(fieldType);
		OneToMany oneToMany = ReflectUtil.getAnnotation(beanClass, fieldName, OneToMany.class);
		ManyToMany manyToMany = ReflectUtil.getAnnotation(beanClass, fieldName, ManyToMany.class);
		String primaryBeanName = beanName;//主方类名，默认为当前，根据多多关系检查后，修改
		Class<?> primaryBeanClass = beanClass;//主方类，默认为当前，根据多多关系检查后，修改
		String primaryFieldName = fieldName;//主方多对多属性名，默认为当前，根据多多关系检查后，修改
		Type primaryFieldType = fieldType;//主方多对多属性类型，默认为当前，根据多多关系检查后，修改
		
		/**********************判断是多对多还是一对多***********************************/
		// 如果是一对多，并且指定了mappedBy
		boolean isOnetoMany = null != oneToMany ;
		if(isOnetoMany)Assert.isTrue(null!=oneToMany.mappedBy(), ServiceCode.ERROR, "一对多必须制定多方维护的属性字段",RsqlConnectionException.class);
		
		// 如果是多对多，不是一对多，则检查多对多关系
		boolean meIsManyToManyPrimary = true;
		if (!isOnetoMany) {
			String tmb = null,mb=null;//多对多中对方属性名称
			if (null != manyToMany) {// 显示声明多对多，双方共同维护。
				// 对方表的集合字段
				Map<String, Method> tcGetters = SqlType.getGetters(subBeanClass, FieldType.TCollection);

				// mb必须主从双方都配置，主方还需配置targetEntity。从方无需配置targetEntity属性。
				mb = manyToMany.mappedBy();

				Assert.notNull(mb, ServiceCode.ERROR,  new StringBuilder("显式指定为双方维护的多对多映射中本类").append(beanClass.getName()).append("没有指定对方类多对多属性:").append(mb).toString(), RsqlConnectionException.class);
				Assert.isTrue(tcGetters.containsKey(mb), ServiceCode.ERROR, new StringBuilder(" 显式指定为双方维护的多对多映射中对方类").append(subBeanClass.getName()).append("不存在该多对多属性:").append(mb).toString(), RsqlConnectionException.class);

				// 获取对方类多对多声明
				ManyToMany tMtm = ReflectUtil.getAnnotation(subBeanClass, mb, ManyToMany.class);
				Assert.notNull(tMtm, ServiceCode.ERROR,  "显示声明多对多时，需要双方指定ManyToMany声明，此处对方类的ManyToMany声明为空！请更正！", RsqlConnectionException.class);
				tmb = tMtm.mappedBy();// 对方类的多对多属性

				Assert.notNull(tmb, ServiceCode.ERROR,  new StringBuilder("显式指定为双方维护的多对多映射中对方类").append(subBeanClass.getName()).append("没有指定本类的多对多属性:").append(mb).toString(), RsqlConnectionException.class);

				Class<?> te = manyToMany.targetEntity(); // 检查主从关系 本类
				Class<?> tte = tMtm.targetEntity(); // 对方类

				Assert.isTrue((null == te && null == tte) || (null != te && null != tte), ServiceCode.ERROR,  new StringBuilder("显式指定为双方维护的多对多映射中，ManyToMany声明不能同时设置或者同时为空！设置targetEntity的为主维护方。").append(mb).toString(),
						RsqlConnectionException.class);

				meIsManyToManyPrimary = ! "void".equals(te.toString());
			} else {
				// 如果不设置manytoMany，则定义为本表本字段为单方维护的多对多，本属性为主维护方。
				// 注意，如果将来需要添加双方维护的多对多，本类的本属性必须指定为主维护方，否则将重建中间表。
				meIsManyToManyPrimary = true;
			}

			//如果不是主表，则修改对应的表名和字段。
			if(!meIsManyToManyPrimary){
				primaryBeanName = subBeanClass.getSimpleName();
				primaryBeanClass = subBeanClass;
				primaryFieldName = mb;//自己mappedby的值刚好是对方的属性
				primaryFieldType = SqlType.getFields(primaryBeanClass, FieldType.TCollection).get(primaryFieldName);
			}
		}// 多对多 end
		

		// 获得外键表的列，此为一对多的collectionTable
		Map<String, ColumnType> ctColumns = obtainListColumnFKColumnType(primaryBeanName, primaryFieldName, primaryFieldType);
		Iterator<Entry<String, ColumnType>> ctkeys = ctColumns.entrySet().iterator();
		String F_column = ctkeys.next().getKey();
		String P_column = ctkeys.next().getKey();
		
		String F_table = StringHelper.getClassSimpleName(subBeanClass);
		String F_table_alias = "T";
		sqlString.append("SELECT ");

		for (String f : SqlType.getGetters(subBeanClass, FieldType.TBase).keySet()) {
			sqlString.append(dialect.aliasFullName(F_table_alias, f, f)).append(",");
		}
		for (String f : SqlType.getGetters(subBeanClass, FieldType.TObject).keySet()) {
			sqlString.append(dialect.aliasFullName(F_table_alias, f, f)).append(",");
		}
		
		// 代码与代码名称映射功能添加。 如果有CodeRef，sql末尾会添加 `,\t\r\n`需要删除,否则只有一个，号要删除
		// LHY 2016-8-5 删除，移除相关Ref代码在本文末
		// boolean hasCodeRef = dealWithCodeRef(spaceName, subBeanClass, F_table_alias, sqlString);
		 sqlString.delete(sqlString.length() - (/*hasCodeRef?4:*/1),sqlString.length());

		sqlString.append(" FROM ").append(dialect.quoteKey(F_table)).append(" ").append(F_table_alias);

		if(isOnetoMany ){
				sqlString.append(" WHERE 1=1 AND ").append(dialect.quoteFullName(F_table_alias, oneToMany.mappedBy())).append("= :RMX_beanId");
		}else {
			String search_column = meIsManyToManyPrimary?P_column:F_column;
			String join_column = meIsManyToManyPrimary?F_column:P_column;
			//多对多从方查询
			sqlString.append(" LEFT JOIN ").append(dialect.quoteKey(obtainListColumnFKTableName(dialect, primaryBeanName, primaryFieldName)))
			.append(" ON ").append(dialect.quoteKey(join_column)).append("=")
			.append(dialect.quoteFullName(F_table_alias, SYS_id));
			sqlString.append(" WHERE 1=1 AND ").append(dialect.quoteKey(search_column)).append("= :RMX_beanId");
		}
		
		HashMap<String, Object> params = new HashMap<String, Object>();
		params.put("RMX_beanId", beanId);
		params.put("RMX_beanClass",subBeanClass);
		return Database.getSession().executeQuery(sqlString.toString(), params);
	}
	/*多对多关系处理-插入*/
	static DbRvo doManyToMany_insert(String spaceName, final Class<?> beanClass, final String beanName, final String fieldName, final Object obj_id, final Object coField_id, final boolean meIsPrimaryTable) {

		Object key = new StringBuilder().append(beanClass.hashCode()).append(beanName.hashCode()).append(fieldName.hashCode()).append(meIsPrimaryTable);
		String doManyToMany_insert_cacheKey = "RsqlUtils.doManyToMany_insert";
		@SuppressWarnings("unchecked")
		ArrayList<String> sqlOpts = (ArrayList<String>) DataCachePool.get(doManyToMany_insert_cacheKey, key );

		if(null==sqlOpts){
			Dialect dialect = RDBManager.getLocalSpaceConfig(spaceName).getDialect();
			StringBuilder sqlString = new StringBuilder();
			ManyToMany manyToMany = ReflectUtil.getAnnotation(beanClass, fieldName, ManyToMany.class);
			Type fieldType = SqlType.getFields(beanClass, FieldType.TCollection).get(fieldName);
			Class<?> subBeanClass = ReflectUtil.getListActualType(fieldType);

			Class<?> primaryBeanClass = beanClass;//主方类，默认为当前，根据多多关系检查后，修改
			String primaryBeanName = beanName;//主方类名，默认为当前，根据多多关系检查后，修改
			String primaryFieldName = fieldName;//主方多对多属性名，默认为当前，根据多多关系检查后，修改
			Type primaryFieldType = fieldType;//主方多对多属性类型，默认为当前，根据多多关系检查后，修改

			if(!meIsPrimaryTable){
				primaryBeanName = subBeanClass.getSimpleName();
				primaryBeanClass = subBeanClass;
				primaryFieldName = manyToMany.mappedBy();//自己mappedby的值刚好是对方的属性
				primaryFieldType = SqlType.getFields(primaryBeanClass, FieldType.TCollection).get(primaryFieldName);
			}

			// 获得外键表的列，此为一对多的collectionTable
			Map<String, ColumnType> ctColumns = obtainListColumnFKColumnType(primaryBeanName, primaryFieldName, primaryFieldType);
			Iterator<String> kitr = ctColumns.keySet().iterator();
			String fkey = kitr.next();
			String pkey = kitr.next();

			sqlString.append("INSERT INTO ")
					.append(dialect.quoteKey(obtainListColumnFKTableName(dialect, primaryBeanName, primaryFieldName)))
					.append(" (\r\n\t");
			// 添加属性外键(F_)在前面,主键在后面(P_)
			sqlString.append(dialect.quoteKey(SYS_id)).append(",");
			sqlString.append(dialect.quoteKey(fkey)).append(",");
			sqlString.append(dialect.quoteKey(pkey));
			sqlString.append("\r\n)VALUES(\r\n\t");
			// 添加命名参数
			sqlString.append(":").append(SYS_id);
			sqlString.append(",:").append(fkey);
			sqlString.append(",:").append(pkey);
			sqlString.append("\r\n)");

			sqlOpts = new ArrayList<String>();
			sqlOpts.add(sqlString.toString());
			sqlOpts.add(pkey);
			sqlOpts.add(fkey);
			sqlOpts.trimToSize();
			DataCachePool.put(doManyToMany_insert_cacheKey, key,sqlOpts);
		}


		Object P_id = meIsPrimaryTable?obj_id:coField_id;
		Object F_id = meIsPrimaryTable?coField_id:obj_id;
		HashMap<String, Object> params = new HashMap<String, Object>();
		params.put(SYS_id, String.valueOf(System.currentTimeMillis())+(100000+Math.random()*10000));
		params.put(sqlOpts.get(1), P_id);
		params.put(sqlOpts.get(2), F_id);
		return Database.getSession().executeUpdate(sqlOpts.get(0),params);
	}
	/*多对多关系处理-删除*/
	static DbRvo doManyToMany_delete(String spaceName, Class<?> beanClass, final String beanName, final String fieldName, final Object obj_id, final Object coField_id, boolean meIsPrimaryTable) {
		Object key = new StringBuilder().append(beanClass.hashCode()).append(beanName.hashCode()).append(fieldName.hashCode()).append(meIsPrimaryTable);
		String doManyToMany_delete_cacheKey = "RsqlUtils.doManyToMany_delete";
		@SuppressWarnings("unchecked")
		ArrayList<String> sqlOpts = (ArrayList<String>) DataCachePool.get(doManyToMany_delete_cacheKey, key );

		if(null==sqlOpts){
			Dialect dialect = RDBManager.getLocalSpaceConfig(spaceName).getDialect();
			StringBuilder sqlString = new StringBuilder();
			// 获得外键表的列，此为一对多的collectionTable
			ManyToMany manyToMany = ReflectUtil.getAnnotation(beanClass, fieldName, ManyToMany.class);
			Type fieldType = SqlType.getFields(beanClass, FieldType.TCollection).get(fieldName);

			Class<?> primaryBeanClass = beanClass;//主方类，默认为当前，根据多多关系检查后，修改
			String primaryBeanName = beanName;//主方类名，默认为当前，根据多多关系检查后，修改
			String primaryFieldName = fieldName;//主方多对多属性名，默认为当前，根据多多关系检查后，修改
			Type primaryFieldType = fieldType;//主方多对多属性类型，默认为当前，根据多多关系检查后，修改

			if(!meIsPrimaryTable){
				Class<?> subBeanClass = ReflectUtil.getListActualType(fieldType);
				primaryBeanName = subBeanClass.getSimpleName();
				primaryBeanClass = subBeanClass;
				primaryFieldName = manyToMany.mappedBy();//自己mappedby的值刚好是对方的属性
				primaryFieldType = SqlType.getFields(primaryBeanClass, FieldType.TCollection).get(primaryFieldName);
			}

			Map<String, ColumnType> ctColumns = obtainListColumnFKColumnType(primaryBeanName, primaryFieldName, primaryFieldType);
			Iterator<String> kitr = ctColumns.keySet().iterator();
			String fkey = kitr.next();
			String pkey = kitr.next();

			sqlString.append("DELETE FROM ").append(dialect.quoteKey(obtainListColumnFKTableName(dialect, primaryBeanName, primaryFieldName)))
					.append(" \r\n\tWHERE ");
			// 添加数据库约束字段
			sqlString.append(dialect.quoteKey(pkey)).append("= :").append(pkey);
			sqlString.append(" AND ");
			sqlString.append(dialect.quoteKey(fkey)).append("= :").append(fkey);

			sqlOpts = new ArrayList<String>();
			sqlOpts.add(sqlString.toString());
			sqlOpts.add(pkey);
			sqlOpts.add(fkey);
			sqlOpts.trimToSize();
			DataCachePool.put(doManyToMany_delete_cacheKey, key,sqlOpts);
		}

		Object P_id = meIsPrimaryTable?obj_id:coField_id;
		Object F_id = meIsPrimaryTable?coField_id:obj_id;

		HashMap<String, Object> params = new HashMap<String, Object>();
		params.put(sqlOpts.get(1), P_id);
		params.put(sqlOpts.get(2), F_id);
		return Database.getSession().executeUpdate(sqlOpts.get(0), params);
	}

	//================================4个核心的生成DML SQL语句的方法============================================//
	public static <T extends Modelable, ParentType extends Modelable> void createDeleteSql(final DbCvo<T, ParentType> cvo) {
		Dialect dialect = RDBManager.getLocalSpaceConfig(cvo._getSpaceName()).getDialect();

		String beanName = cvo.getBeanName();
		String tableAliasName = beanName;

		ArrayList<NamedParam> namedParams = new ArrayList<NamedParam>();
		cvo._setNamedParams(namedParams);
		cvo._setTableAliasName(tableAliasName);
		namedParams.add(new NamedParam(-1, SYS_id, Types.CHAR, null));

		Param<Integer> tableIndex = new Param<>(0);// 用于控制数据库虚拟表明的序号。
		Param<Integer> paramIndex = new Param<>(0);// 用于控制数据库参数的序号。

		String part_where = "\r\nWHERE 1=1 " + (Judgment.nullOrBlank(cvo.getId())?"":" AND"+dialect.quoteKey(SYS_id) + "= :"+SYS_id);
		String filterStr = cvo.getFilter().toSQL(false, tableAliasName, namedParams, paramIndex, tableIndex, cvo);
		if(!Judgment.nullOrBlank(filterStr))
			part_where += ((" AND (") + filterStr+") ");

		// 删除多余空间
		namedParams.trimToSize();
		cvo._setSqlString("DELETE FROM " + dialect.quoteKey(beanName)  + part_where);
	}
	public static <T extends Modelable, ParentType extends Modelable> void createInsertSql(final DbCvo<T, ParentType> cvo) {
		Dialect dialect = RDBManager.getLocalSpaceConfig(cvo._getSpaceName()).getDialect();

		String beanName = cvo.getBeanName();
		Class<?> beanClass=cvo.getBeanClass();
		String tableName = beanName;

		ArrayList<NamedParam> namedParams = new ArrayList<>();
		cvo._setNamedParams(namedParams);


		// 定义对象类型数据的查询sql
		String prefix = "INSERT INTO "+dialect.openQuote() + tableName+dialect.closeQuote();
		String part_col2val = ")\r\n VALUES \r\n\t(";
		StringBuilder part_column_sb = new StringBuilder();
		StringBuilder part_value_sb = new StringBuilder();

		StringBuilder sqlString = new StringBuilder();

		// 定义完整set field=**数据insert语句(id为默认自动索引)
		part_column_sb.append("\r\n\t(");
		// 插入系统配置列
		SysColumns.forEach((column,columnType)->{
			part_column_sb.append(dialect.quoteKey(column)).append(",");
			part_value_sb.append(":").append(column).append(",");
			namedParams.add(new NamedParam(-1, column, columnType.type, null));
		});
		// 插入基础数据
		Map<String, ColumnType> baseColumns = RsqlUtils.obtainColumnType(beanClass, cvo._getRootColumn(), FieldType.TBase);
		baseColumns.forEach((column,columnType)-> {
			part_column_sb.append(dialect.quoteKey(column)).append(",");
			part_value_sb.append(":").append(column).append(",");
			namedParams.add(new NamedParam(-1, column, columnType.type, null));
		});
		// 插入对象数据
		Map<String, ColumnType> objectColumns = RsqlUtils.obtainColumnType(beanClass, cvo._getRootColumn(), FieldType.TObject);
		objectColumns.forEach((column,columnType)-> {
			part_column_sb.append(dialect.quoteKey(column)).append(",");
			part_value_sb.append(":").append(column).append(",");
			namedParams.add(new NamedParam(-1, column, columnType.type, null));
		});
		part_value_sb.append(")\r\n");

		//拼接语句
		String part_column = part_column_sb.deleteCharAt(part_column_sb.length() - 1).toString();// 删除最后一个逗号
		String part_value = part_value_sb.deleteCharAt(part_value_sb.length() - 4).toString();// 删除最后一个逗号
		sqlString.append(prefix).append(part_column).append(part_col2val).append(part_value);
		// 删除多余空间
		namedParams.trimToSize();
		cvo._setSqlString(sqlString.toString());
	}
	public static <T extends Modelable, ParentType extends Modelable> void createSelectSql(final DbCvo<T, ParentType> cvo) {
		Select select = new Select<>(cvo);
		if(!cvo._isHasGroupBy() &&!cvo._isHasAggregateBy() && !cvo._isHasDistinct()){
			if(!cvo._isSubStatment())
				select.appendBaseColumn(SYS_id, SYS_id);
				// select.appendBaseColumn(SYS_name, SYS_name);
		}

		//当前表的基本列是否显示添加，如果没有则默认添加当前表的所有base字段
		Param<Boolean> hasNotBaseColumn = new Param<>(true);
		//Object处理 List属性处理
		cvo._getRootColumn().getSubColumns().stream()
				.forEach(c -> c.forEvery(cc -> {
					if (FieldType.TBase.equals(cc.getType())){
						select.appendColumn(cc);
						if(hasNotBaseColumn.param)
							hasNotBaseColumn.param = !FieldType.TROOT.equals(cc.getSupColumn().getType()); // 如果Tbase且父为根node，则说明手动添加了当前表的字段。
					}else if (FieldType.TObject.equals(cc.getType()))
						select.leftJoinModel(cc);//连接外键对象
					else if (FieldType.TCollection.equals(cc.getType()))
						select.leftJoinList(cc);//连接一对多，多对多等。

					//处理groupby
					if(cc.isGroupBy())
						select.groupBy(cc);

				}));

		//默认没有明确指定要查询的列时，且不是子句/聚合/分组，则添加基本列
		if(hasNotBaseColumn.param && ! cvo._isSubStatment() && !cvo._isHasGroupBy() && !cvo._isHasAggregateBy() && !cvo._isHasDistinct()){
			Class<?> beanClass=cvo.getBeanClass();
			Map<String, ColumnType> baseColumns = RsqlUtils.obtainColumnType(beanClass, null/*cvo._getRootColumn(),因为已经判断是没有使用with方法限定列，所以此处不要传rootColumn限制查询列*/, FieldType.TBase);
			baseColumns.forEach((fieldName, ct) -> select.appendBaseColumn(fieldName, fieldName));
		}else if(hasNotBaseColumn.param && cvo._isSubStatment()){
			//没有指定要查询的列且是子句的时候，是否应该添加默认的id列？ TODO，目前有添加，通过手动withColumns添加

		}
		//end for Base Object List属性处理

		cvo._setSqlString(select.sqlString());
	}
	public static <T extends Modelable, ParentType extends Modelable> void createStringSql(final DbCvo<T, ParentType> cvo) {
		Dialect dialect = RDBManager.getLocalSpaceConfig(cvo._getSpaceName()).getDialect();
		String sqlString = cvo._getSqlString();
		
		//对数据库字典进行转换
		//sqlString = replaceRefCode(cvo._getSpaceName(),sqlString);
		
		String regex= dialect.obtainSelectRegex();
		MatchResult mr = StringHelper.match(sqlString, regex,null);
		@SuppressWarnings("unused")
		String tableAliasName = null,tableName=null;
		if(null!=mr){
			tableName = mr.group(1);
			tableAliasName = mr.group(2);
			cvo.$S(PN_bn, tableName);//解析获取sql中的表名。
		}
		
		ArrayList<NamedParam> namedParams = new ArrayList<>();
		cvo._setNamedParams(namedParams);

//		sqlBean.setTableName(_tableAliasName==null || "WHERE".equals(_tableAliasName.toUpperCase())?tableName:_tableAliasName);
		
		TreeMap<Integer, String> paramIndexs = RsqlUtils.obtainNamedParamIndexs(sqlString);
		for(Integer paramIdx:paramIndexs.keySet()){
			namedParams.add(new NamedParam(-1, paramIndexs.get(paramIdx), Types.CHAR, null));
		}
		// 删除多余空间
		namedParams.trimToSize();
		cvo._setSqlString(sqlString.toString());
	}
	public static <T extends Modelable, ParentType extends Modelable> void createUpdateSql(final DbCvo<T, ParentType> cvo) {
		Dialect dialect = RDBManager.getLocalSpaceConfig(cvo._getSpaceName()).getDialect();

		String beanName = cvo.getBeanName();
//		sqlBean.setTableName(beanName);
		Class<?> beanClass=cvo.getBeanClass();
		String tableAliasName = "T";

		List<NamedParam> namedParams = new ArrayList<>();
		cvo._setNamedParams(namedParams);//子查询需要用，得提前初始化
		cvo._setTableAliasName(tableAliasName);
		namedParams.add(new NamedParam(-1, SYS_id, Types.CHAR, null));

		Param<Integer> tableIndex = new Param<>(0);// 用于控制数据库虚拟表明的序号。
		Param<Integer> paramIndex = new Param<>(0);// 用于控制数据库参数的序号。

		// 定义对象类型数据的查询sql
		String prefix = "UPDATE "+dialect.quoteKey(beanName)+" "+tableAliasName+ " SET ";
		String part_colsetval;
		String part_where = "\r\nWHERE 1=1 " + (Judgment.nullOrBlank(cvo.getId())?"":" AND"+dialect.quoteKey(SYS_id) + "= :"+SYS_id);
		String filterStr = cvo.getFilter().toSQL(false, tableAliasName, namedParams, paramIndex, tableIndex, cvo);
		if(!Judgment.nullOrBlank(filterStr))
			part_where += ((" AND (") + filterStr+") ");

		StringBuilder part_colsetval_sb = new StringBuilder();
		StringBuilder sqlString = new StringBuilder();

		BiConsumer<? super String, ? super ColumnType> columnBiConsumer = (column, columnType) -> {
			SqlColumn<ParentType, T, T, T> curSqlColumn = cvo._getRootColumn().subColumn(column);
			if (curSqlColumn!= null && null != curSqlColumn.getSubDbCvo()) {
				//noinspection unchecked
				curSqlColumn.getSubDbCvo()._initForSubStatement(cvo,tableIndex,paramIndex);
				part_colsetval_sb.append("\r\n\t").append(dialect.quoteKey(column)).append("= (").append(curSqlColumn.getSubDbCvo()._getPrettySqlString()).append("),");
			} else if(curSqlColumn!= null && curSqlColumn._isNotWith()) {
				//做了 isNotWith标志的,不用更新
			} else{
				part_colsetval_sb.append("\r\n\t").append(dialect.quoteKey(column)).append("= :").append(column).append(",");
				namedParams.add(new NamedParam(-1, column, columnType.type, null));
			}
		};


		// 定义完整set field=**数据 update 语句(id为默认自动索引)
		// 插入系统配置列
		SysModifyColumns.forEach(columnBiConsumer);

		// 添加基本列数据
		Map<String, ColumnType> baseColumns = RsqlUtils.obtainColumnType(beanClass, cvo._getRootColumn(), FieldType.TBase);
		baseColumns.forEach(columnBiConsumer);
		// 添加对象列数据
		Map<String, ColumnType> objectColumns = RsqlUtils.obtainColumnType(beanClass, cvo._getRootColumn(), FieldType.TObject);
		objectColumns.forEach(columnBiConsumer);

		// 拼接语句
		part_colsetval = part_colsetval_sb.deleteCharAt(part_colsetval_sb.length() - 1).toString();// 删除最后一个逗号
		sqlString.append(prefix).append(part_colsetval).append(part_where);
		cvo._setSqlString(sqlString.toString());
	}

	//================================4个核心的生成DDL SQL语句的方法============================================//
	/* 向表中添加一个数据列。*/
	static void alterAddColumn(final Dialect dialect, final String tableName, final String columnName, final ColumnType columnType) {
		String sqlString = "ALTER TABLE " + dialect.quoteKey(tableName) + " ADD " + dialect.quoteKey(columnName) + "" +
				dialect.obtainSQLTypeString(columnType);
		Database.getSession().executeUpdate(sqlString, null);
	}
	/* 修改表中的一个数据列。*/
	static void alterModifyColumn(final Dialect dialect, final String tableName, final String columnName, final ColumnType columnType, String renameFrom) {
		// alter table tablename modify  columnName varchar(len);
		String sqlString;
		if(Judgment.nullOrBlank(renameFrom)){
			sqlString = "ALTER TABLE " + dialect.quoteKey(tableName) + " MODIFY " + dialect.quoteKey(columnName) + "" +
					dialect.obtainSQLTypeString(columnType);
		}else{
			sqlString = dialect.renameColumnSql().replaceAll(":tableName",dialect.quoteKey(tableName)).replaceAll(":oldColumnName",dialect.quoteKey(renameFrom)).replaceAll(":newColumnName",dialect.quoteKey(columnName))+" "+dialect.obtainSQLTypeString(columnType);
		}

		Database.getSession().executeUpdate(sqlString, null);
	}
	/*本程序用于自动创建JavaBean对应的关系型数据表基本结构 仅支持Int nvarchar两种数据类型*/
	static void createBaseTable(final Dialect dialect, final String tableName, final Class<?> beanClass) {
		String prefix = "\r\nCREATE TABLE " + dialect.quoteKey(tableName) + " (\r\n";
		String suffix = "\r\n)\r\n";
		StringBuilder content = new StringBuilder();

		// 系统数据列
		SysColumns.forEach((sysColumn,ct)->{
			content.append("		").append(dialect.quoteKey(sysColumn)).append(dialect.obtainSQLTypeString(ct)).append(sysColumn.equals(SYS_id)?" NOT NULL PRIMARY KEY,\r\n":" NULL,\r\n");
		});

		// ****************添加bean中的基本数据属性，定义为数据库中的字段
		RsqlUtils.obtainColumnType(beanClass, null, FieldType.TBase).forEach((baseColumn, ct) ->
				content.append("		").append(dialect.quoteKey(baseColumn)).append(dialect.obtainSQLTypeString(ct)).append(" NULL,\r\n"));

		// *****************添加bean中的表连接属性，定义为int，并随后建立表外键连接
		RsqlUtils.obtainColumnType(beanClass, null, FieldType.TObject).forEach((objectColumn, ct) ->
				content.append("		").append(dialect.quoteKey(objectColumn)).append(dialect.obtainSQLTypeString(ct)).append(" NULL,\r\n"));

		String mid = content.toString().substring(0, content.length() - 3);//删除末尾的逗号换行3个字符

		Database.getSession().executeUpdate(prefix + mid + suffix, null);
	}
	/*此函数建立bean中List/Set/Vector关联的表*/
	static void createCollectionTable(final Dialect dialect, final String beanName, final String fieldName, final Type fieldType) {

		// 因为获取的就是List、Set、Vector类型，所以一定是ParameterizedTypeImpl，且ActualTypeArguments是一个参数
//		ParameterizedTypeImpl typeImpl = (ParameterizedTypeImpl) fieldType;
//		Type[] types = typeImpl.getActualTypeArguments();
		Type[] types = ReflectUtil.getActualTypeArguments(fieldType);

		// 获取本表的必须列，共两列，是确定的
		Map<String, ColumnType> columns = RsqlUtils.obtainListColumnFKColumnType(beanName, fieldName, fieldType);

		String tableName = RsqlUtils.obtainListColumnFKTableName(dialect, beanName, fieldName);
		String prefix = "CREATE TABLE " + dialect.quoteKey(tableName);
		String suffix = "\r\n)\r\n";

		StringBuilder content = new StringBuilder("(\n");
		for (Type type1 : types) {
			if (SqlType.isTCollection(type1)) {
				throw new RsqlConnectionException(beanName, "不支持深层Collection映射，数据库ORM映射创建失败！");
			} else if (type1 == Object.class) {
				throw new RsqlConnectionException(beanName, "不支持Object 原始类型直接Map映射，数据库ORM映射创建失败！");
			}
		}

		content.append("		").append(dialect.quoteKey(SYS_id)).append(" ").append(dialect.obtainSQLTypeString(new ColumnType(Types.CHAR, 50))).append(" NOT NULL PRIMARY KEY,\r\n");
		// *****************添加bean中的表连接属性，定义为int，并随后建立表外键连接
		for (String objectColumn : columns.keySet()) {
			ColumnType ct =columns.get(objectColumn);
			content.append("		").append(dialect.quoteKey(objectColumn)).append(dialect.obtainSQLTypeString(ct)).append(" NOT NULL,\r\n");
		}

		String mid = content.toString();
		mid = mid.substring(0, mid.length() - 3);
		Database.getSession().executeUpdate(prefix + mid + suffix, null);
	}

	//================================2个多对多中间表的DDL SQL语句的方法============================================//
	/*获取一对多关系表的名称。如AuthUser表中有roles(指向AuthRole)，则表名为AuthUser_roles*/
	public static String obtainListColumnFKTableName(final Dialect dialect, final String primaryBeanName, final String primaryFieldName) {
		return primaryBeanName + "_" + primaryFieldName;
	}
	/*生成一对多的数据库表的必须列。 包含P_主表名,F_外表名，返回的treeMap中FK在前面，PK在后面。*/
	public static Map<String, ColumnType> obtainListColumnFKColumnType(final String beanName, final String fieldName, final Type fieldType) {
		Type[] types = (Type[]) ReflectUtil.invokeMethod("getActualTypeArguments", fieldType);
		// 因为获取的就是Collection类型，所以一定是ParameterizedTypeImpl，且ActualTypeArguments是一个参数
		TreeMap<String, ColumnType> neededColumns = new TreeMap<>();

		// 一对多，一方,一方一定是一个id 索引
		neededColumns.put("P_" + beanName, new ColumnType(Types.CHAR,50));
		// 一对多，多方
		neededColumns.put("F_" + StringHelper.getClassSimpleName(types[0]), obtainSQLType(types[0], null, null));

		return neededColumns;
	}

	//================================数据字典在SQL语句中的映射转换方法，现在通过前端的rmx.dic组件解决映射问题，应该没用了，暂时注解掉============================================//
//	@SuppressWarnings("unused")
//    public static boolean dealWithCodeRef(String spaceName, Class<?> beanClass, String tableAliasName, StringBuilder part_column_sb){
//		// 代码与代码名称映射功能添加。
//		// 此处是【值映射】
//		// 支持三种方式:
//		//1.表中字段的代码映射功能来源于DataDic系统数据字典表
//		//2.表中字段的代码映射功能来源于本地表的某两个字段，一个字段用于保存于本表本字段中，另一个用于前端页面显示
//		//3.表中字段的代码映射功能来源于每个服务提供的查询 TODO 此功能很底层，暂不实现
//		if(true){ // 开启代码映射功能，默认开启
//			//获取需要代码映射的字段
//			Map<String, ColumnType> RefColumns = RsqlUtils.obtainSKeyColumnsRef(beanClass, SqlType.getFields(beanClass,FieldType.TBase)); // 值映射在数据库中都是保存于base列中的
//
//			for(String fieldName:RefColumns.keySet()){
//				//从该字段中判断是以上那种类型
//				ColumnType ct = RefColumns.get(fieldName);
//				if(EditType.CodeRef == ct.editType){
//					//通过预读取采用encode函数减少
//					StringBuilder sb = obtainRsqlDecodePart(spaceName, tableAliasName, fieldName, ct);
//					part_column_sb.append(sb).append(",\r\n\t");
//				}
//			}
//			return RefColumns.size()>0;
//		}else{
//			return false;
//		}
//	}
//
//	private static Map<String, ColumnType> obtainSKeyColumnsRef(
//			Class<?> beanClass, Map<String, Type> fields) {
//		Map<String, Type> baseFields = SqlType.getFields(beanClass,FieldType.TBase);
//		Map<String, ColumnType> rets = new HashMap<String, ColumnType>();
//		for(String field:baseFields.keySet()){
//			Element ele = ReflectUtil.getAnnotation(beanClass, field, Element.class);
//			if(null!=ele && EditType.CodeRef == ele.edittype()){
//				ColumnType ct = obtainSQLType(baseFields.get(field), field, beanClass);
//				ct.editType = EditType.CodeRef;
//				ct.codeRefBean = ele.CodeRefBean();
//				ct.codeRefCodeColumn = ele.CodeRefCodeColumn();
//				ct.codeRefCodeType = Judgment.nullOrBlank(ele.CodeRefCodeType())?field:ele.CodeRefCodeType();
//				ct.codeRefDescColumn = ele.CodeRefDescColumn();
//				ct.codeRefTypeColumn = ele.CodeRefTypeColumn();
//				ct.codeRefFilters = ele.CodeRefFilters();
//				rets.put(field, ct );
//			}
//		}
//
//		return rets;
//	}
//	/**
//	 *
//
//	 */
//	public static String replaceRefCode(String spaceName, String orgnSql){
//		// 条件匹配  表.列,别名,匹配表,匹配表条件列,条件,（条件咧=条件）,被匹配列,被匹配名
//		RDBSpaceConfig spaceConfig = RDBManager.getLocalSpaceConfig(spaceName);
//		Dialect dialect = spaceConfig.getDialect();
//		final char t = dialect.openQuote() ;
//		final  String RefCodeRegx = "RefCode\\((\\w+)\\."+t+"(\\w+)"+t+","+t+"(\\w+)"+t+","+t+"(\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+","+t+"(\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+"\\)";
//		final  String RefCodeRegx5 = "RefCode\\(substr\\((\\w+)\\."+t+"(\\w+)"+t+",0,2\\),"+t+"(\\w+)"+t+","+t+"(\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+","+t+"(\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+"\\)";
//		final  String RefCodeRegx6 = "RefCode\\(substr\\((\\w+)\\."+t+"(\\w+)"+t+",0,2\\),"+t+"(\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+","+t+"(\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+"\\)";
//		// 无条件匹配     表.列,别名,匹配表,被匹配列,被匹配名
//		final String RefCodeRegx2="RefCode\\((\\w+)\\."+t+"(\\w+)"+t+","+t+"(\\w+)"+t+","+t+"(\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+"\\)";
//		// 条件无别名匹配     表.列,匹配表,匹配表条件列,条件,（条件咧=条件）,被匹配列,被匹配名
//		final  String RefCodeRegx3 = "RefCode\\((\\w+)\\."+t+"(\\w+)"+t+","+t+"(\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+","+t+"(\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+"\\)";
//		// 无条件无别名匹配    表.列 , 匹配表,被匹配列,被匹配名
//		final String RefCodeRegx4="RefCode\\((\\w+)\\."+t+"(\\w+)"+t+","+t+"(\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+","+t+"(\\w+|\\w+\\.\\w+)"+t+"\\)";
//		// 省 查到市
//		MatchResult rs;
//		while(null!=(rs = StringHelper.match(orgnSql, RefCodeRegx, null))){
//			String fieldTable = rs.group(1);
//			String fieldName = rs.group(2);
//			String displayName = rs.group(3);
//			String codeTbName = rs.group(4);
//			String refTypeColumn = rs.group(5);
//			String refCodeType = rs.group(6);
//			String codeColumn = rs.group(7);
//			String descColumn = rs.group(8);
//
//			StringBuilder decodeSqlPart = obtainDecodeSqlPart(spaceName, fieldTable,fieldName,displayName,codeTbName,refTypeColumn,refCodeType,codeColumn,descColumn,false);
//
//			orgnSql = StringHelper.substitute(orgnSql, RefCodeRegx, decodeSqlPart.toString(),1);
//		}
//		while(null!=(rs = StringHelper.match(orgnSql, RefCodeRegx5, null))){
//			String fieldTable = rs.group(1);
//			String fieldName = rs.group(2);
//			String displayName = rs.group(3);
//			String codeTbName = rs.group(4);
//			String refTypeColumn = rs.group(5);
//			String refCodeType = rs.group(6);
//			String codeColumn = rs.group(7);
//			String descColumn = rs.group(8);
//
//			StringBuilder decodeSqlPart = obtainDecodeSqlPart(spaceName, fieldTable,fieldName,displayName,codeTbName,refTypeColumn,refCodeType,codeColumn,descColumn,true);
//
//			orgnSql = StringHelper.substitute(orgnSql, RefCodeRegx5, decodeSqlPart.toString(),1);
//		}
//		while(null!=(rs = StringHelper.match(orgnSql, RefCodeRegx2, null))){
//			String fieldTable = rs.group(1);
//			String fieldName = rs.group(2);
//			String displayName = rs.group(3);
//			String codeTbName = rs.group(4);
//			String codeColumn = rs.group(5);
//			String descColumn = rs.group(6);
//
//			StringBuilder decodeSqlPart = obtainDecodeSqlPart(spaceName, fieldTable,fieldName,displayName,codeTbName,null,null,codeColumn,descColumn,false);
//
//			orgnSql = StringHelper.substitute(orgnSql, RefCodeRegx2,decodeSqlPart.toString(),1);
//		}
//		while(null!=(rs = StringHelper.match(orgnSql, RefCodeRegx3, null))){
//			String fieldTable = rs.group(1);
//			String fieldName = rs.group(2);
//			String codeTbName = rs.group(3);
//			String refTypeColumn = rs.group(4);
//			String refCodeType = rs.group(5);
//			String codeColumn = rs.group(6);
//			String descColumn = rs.group(7);
//
//			StringBuilder decodeSqlPart = obtainDecodeSqlPart(spaceName, fieldTable,fieldName,null,codeTbName,refTypeColumn,refCodeType,codeColumn,descColumn,false);
//
//			orgnSql = StringHelper.substitute(orgnSql, RefCodeRegx3, decodeSqlPart.toString(),1);
//		}
//		while(null!=(rs = StringHelper.match(orgnSql, RefCodeRegx6, null))){
//			String fieldTable = rs.group(1);
//			String fieldName = rs.group(2);
//			String codeTbName = rs.group(3);
//			String refTypeColumn = rs.group(4);
//			String refCodeType = rs.group(5);
//			String codeColumn = rs.group(6);
//			String descColumn = rs.group(7);
//
//			StringBuilder decodeSqlPart = obtainDecodeSqlPart(spaceName, fieldTable,fieldName,null,codeTbName,refTypeColumn,refCodeType,codeColumn,descColumn,true);
//
//			orgnSql = StringHelper.substitute(orgnSql, RefCodeRegx6, decodeSqlPart.toString(),1);
//		}
//		while(null!=(rs = StringHelper.match(orgnSql, RefCodeRegx4, null))){
//			String fieldTable = rs.group(1);
//			String fieldName = rs.group(2);
//			String codeTbName = rs.group(3);
//			String codeColumn = rs.group(4);
//			String descColumn = rs.group(5);
//
//			StringBuilder decodeSqlPart = obtainDecodeSqlPart(spaceName, fieldTable,fieldName,null,codeTbName,null,null,codeColumn,descColumn,false);
//
//			orgnSql = StringHelper.substitute(orgnSql, RefCodeRegx4, decodeSqlPart.toString(),1);
//		}
//		return orgnSql;
//	}
//	@Deprecated
//	private static StringBuilder obtainDecodeSqlPart(
//			String spaceName, final String fieldTable,  //表明
//			final String fieldName,        // 表列
//			final String displayName,    // 表别名
//			final String codeTableName,    // 关联表名
//			final String refTypeColumn, // 关联列 的筛选    用于筛选
//			final String refCodeType,    // 筛选的值
//			final String codeColumn,    // 关联列
//			final String descColumn,        // 关联列的值
//			final boolean hasSubStr //需要decode的sql中存在substr函数
//	){
//		RDBSpaceConfig spaceConfig = RDBManager.getLocalSpaceConfig(spaceName);
//		Dialect dialect = spaceConfig.getDialect();
//		@SuppressWarnings("unchecked")
//		Class<Modelable> clazz = (Class<Modelable>) spaceConfig.getOrmBeanClass(codeTableName);
//		DbCvo dbCvo = Database.createDbCvo(clazz);
//		if(null!=refTypeColumn && null!=refCodeType)
//			dbCvo.addRule(refTypeColumn,WhereRuleOper.eq,refCodeType);
//		DbRvo rvo = dbCvo.ready().query();
//		Map<String, String> map = rvo.obtainMap(codeColumn, descColumn);
//
//		Assert.isTrue(map!=null && map.size()>0, ServiceCode.ERROR,  "配置的值参照中没有相应的参数！请配置人员查阅数据表:"+codeTableName);
//		return  dialect.obtainDecodeSQL(map, hasSubStr?"substr("+dialect.quoteFullName(fieldTable, fieldName)+",0,2)":dialect.quoteFullName(fieldTable, fieldName), displayName);
//	}
//	@Deprecated
//	private static StringBuilder obtainRsqlDecodePart(String spaceName,
//			final String curTableAliasName,final String fieldName,
//			final ColumnType ct
//			){
//		final String DataDicTb = StringHelper.getClassSimpleName(ct.codeRefBean);
//		final String typeColumn = ct.codeRefTypeColumn;
//		final String codeType = ct.codeRefCodeType;
//		final String codeColumn = ct.codeRefCodeColumn;
//		final String descColumn = ct.codeRefDescColumn;
//		final String codeRefFilters = ct.codeRefFilters;
//
//		RDBSpaceConfig spaceConfig = RDBManager.getLocalSpaceConfig(spaceName);
//		Dialect dialect = spaceConfig.getDialect();
//		@SuppressWarnings("unchecked")
//		Class<Modelable> clazz = (Class<Modelable>) spaceConfig.getOrmBeanClass(DataDicTb);
//
//		DbCvo dbCvo = Database.createDbCvo(clazz);
//		//如果通过filters约束要搜索的数据字典的字段，则filters有限
//		if(!Judgment.nullOrBlank(codeRefFilters)){
//			Where sbw = JsonHelper.toJavaObject(codeRefFilters, Where.class);
//			dbCvo.filter(sbw);
//		}else{//默认通过dataType=来匹配搜索
//			dbCvo.addRule(typeColumn, WhereRuleOper.eq, codeType);
//		}
//		DbRvo rvo = dbCvo.ready().query();
//		Map<String, String> map = rvo.obtainMap(codeColumn, descColumn);
//
//		Assert.isTrue(map!=null && map.size()>0, ServiceCode.ERROR,  "配置的值参照中没有相应的参数！请配置人员查阅数据表:"+DataDicTb);
//
//		StringBuilder sb = dialect.obtainDecodeSQL(map, dialect.quoteFullName(curTableAliasName, fieldName), "RMX_"+DataDicTb+"_"+fieldName);
//		return sb;
//
//	}





}

